import React, { Component } from 'react'

// 装饰器 es7提出来的，用于装饰类所用，它只能装饰类
// 装饰器它就是一个函数，此函数可以用来对于类来完成装饰

// // target参数就是当前Demo类
// const fn = target => {
//   // console.log(target)

//   // 扩展一个成员属性  给类扩展一个成员属性
//   target.prototype.name = '李四'

//   // 成员方法
//   target.prototype.run = function () {
//     console.log('run方法')
//   }

//   // 静态方法  通过类来调用
//   target.test = function () {
//     console.log('test方法')
//   }
// }

// // 装饰类
// @fn
// class Demo {}
// const d = new Demo()
// // console.log(d)
// // 调用成员方法
// d.run()
// // 调用静态方法
// Demo.test()

// 装饰器，装饰时有写小括号，则需要返回一个函数
// 第1个函数中的参数，则为装饰器中小括号的传入过来的内容
// 返回的函数的参数就是当前的装饰类
// const fn = (age, name) => target => {
//   // console.log(age, name)
//   // console.log(target)

//   target.prototype.name = name
//   target.prototype.age = age
// }

// @fn(1, '张三')
// class Demo {}

// const d = new Demo()
// console.log(d)

// target当前类的实例对象
// key就是当前的成员属性的名称
// description 关于此成员属性的描述
// const readonly = (target, key, description) => {
//   // console.log(target,key,description)
//   // Object.defineProperty
//   description.writable = false
// }

// class Demo {
//   // 通过装饰器来让成员属性只读
//   @readonly
//   name = '张三'
// }

// const d = new Demo()
// d.name = '李四'

const fn = (target, key, description) => {
  // console.log(target,key,description)
  // 对于原有的方法时行增量添加
  // 对象中的原方法进行暂时的保存起来
  let oldFn = description.value
  description.value = function (...arg) {
    // 调用原方法时，要注意this的指向问题 call/apply
    // oldFn.apply(this, arg)
    oldFn.call(this, ...arg)
    console.log('装饰器中的方法')
  }
}

class Demo {
  name = '赵六'
  @fn
  push(arg) {
    console.log(this)
    console.log('demo -- push', arg, this.name)
  }
}

const d = new Demo()
d.push('变异')

class App extends Component {
  render() {
    return <div>App</div>
  }
}

export default App
